home *** CD-ROM | disk | FTP | other *** search
/ Programming a Multiplayer FPS in DirectX / Programming a Multiplayer FPS in DirectX (Companion CD).iso / DirectX / dxsdk_oct2004.exe / dxsdk.exe / Samples / Managed / Direct3D / HDRCubeMap / HDRCubeMap.cs next >
Encoding:
Text File  |  2004-09-28  |  54.7 KB  |  1,200 lines

  1. //-----------------------------------------------------------------------------
  2. // File: HDRCubeMap.cs
  3. //
  4. // The sample demonstrates high dynamic range lighting with cube maps
  5. //
  6. // Copyright (c) Microsoft Corporation. All rights reserved.
  7. //-----------------------------------------------------------------------------
  8.  
  9.  
  10. //#define DEBUG_VS   // Uncomment this line to debug vertex shaders 
  11. //#define DEBUG_PS   // Uncomment this line to debug pixel shaders 
  12.  
  13. using System;
  14. using Microsoft.DirectX;
  15. using Microsoft.DirectX.Direct3D;
  16. using Microsoft.Samples.DirectX.UtilityToolkit;
  17.  
  18. namespace HDRCubeMapSample
  19. {
  20.     /// <summary>Structure used to hold the orbit data</summary>
  21.     struct OrbitData
  22.     {
  23.         public string MeshFile; // XFile name
  24.         public Vector3 Axis; // Axis of rotation
  25.         public float Radius; // Orbit radius
  26.         public float Speed; // Orbit speed in radians per second
  27.         
  28.         /// <summary>Create a new instance of this object</summary>
  29.         public OrbitData(string mesh, Vector3 rotation, float r, float s)
  30.         {
  31.             MeshFile = mesh; Axis = rotation; Radius = r; Speed = s;
  32.         }
  33.     }
  34.  
  35.     /// <summary>Encapsulate an object in the scene with its world transformation matrix</summary>
  36.     class SceneObject
  37.     {
  38.         public Matrix WorldMatrix = Matrix.Identity; // World transformation
  39.         public FrameworkMesh Mesh; // Mesh object
  40.  
  41.         /// <summary>Create a new instance</summary>
  42.         public SceneObject(FrameworkMesh m) { Mesh = m; }
  43.  
  44.         /// <summary>
  45.         /// Compute the world transformation matrix to center the mesh at origin in world space
  46.         /// and scale its size to the specified radius.
  47.         /// </summary>
  48.         public void WorldCenterAndScaleToRadius(float radius)
  49.         {
  50.             // Compute bounding sphere
  51.             Vector3 center;
  52.             float radiusBound = Mesh.ComputeBoundingSphere(out center);
  53.  
  54.             // Translate and scale
  55.             float scaleFator = radius / radiusBound;
  56.             WorldMatrix = Matrix.Translation(-center) * Matrix.Scaling(scaleFator, scaleFator, scaleFator);
  57.         }
  58.     }
  59.  
  60.     /// <summary>Encapsulate an orbiter object in the scene with related data</summary>
  61.     class Orbiter : SceneObject
  62.     {
  63.         private Vector3 axis = new Vector3(0.0f, 1.0f, 0.0f); // orbit axis
  64.         private float radius = 1.0f; // Orbit radius
  65.         private float speed = (float)Math.PI; // Orbit speed in radians per second
  66.  
  67.         /// <summary>Create a new instance</summary>
  68.         public Orbiter(FrameworkMesh m) : base(m) {  }
  69.  
  70.         /// <summary>Call this after the world matrix is initialized</summary>
  71.         public void SetOrbit(Vector3 rotation, float r, float s)
  72.         {
  73.             // Normalize the rotation
  74.             rotation.Normalize();
  75.             // Store the variables
  76.             axis = rotation; radius = r; speed = s;
  77.  
  78.             // Translate by radius in the -Y direction
  79.             Matrix m = Matrix.Translation(0.0f, -radius, 0.0f);
  80.             WorldMatrix *= m;
  81.  
  82.             // Apply rotation from X axis to orbit axis
  83.             Vector3 xAxis = new Vector3(1.0f, 0.0f, 0.0f);
  84.             Vector3 rotationVector = Vector3.Cross(axis, xAxis); // Axis of rotation
  85.             
  86.             // If the cross product is 0, axis is on the X axis
  87.             // So we either rotate 0 or PI.
  88.             if (rotationVector.LengthSq() == 0)
  89.             {
  90.                 if (axis.X < 0.0f)
  91.                     m = Matrix.RotationY((float)Math.PI);
  92.                 else
  93.                     m = Matrix.Identity;
  94.             }
  95.             else
  96.             {
  97.                 float angle = (float)Math.Acos(Vector3.Dot(axis, xAxis) ); // Angle to rotate
  98.                 // Find out direction to rotate
  99.                 Vector3 xCrossRot = Vector3.Cross(xAxis, rotationVector);
  100.                 if (Vector3.Dot(xCrossRot, axis) >= 0)
  101.                     angle = -angle;
  102.                 
  103.                 // Calculate the rotation
  104.                 m = Matrix.RotationAxis(rotationVector, angle);
  105.             }
  106.             
  107.             // Update world matrix
  108.             WorldMatrix *= m;
  109.         }
  110.  
  111.         /// <summary>Compute the orbit transformation and apply to WorldMatrix</summary>
  112.         public void Orbit(float elapsedTime)
  113.         {
  114.             WorldMatrix *= Matrix.RotationAxis(axis, speed * elapsedTime);
  115.         }
  116.     }
  117.  
  118.     /// <summary>Encapsulate a light object in the scene with related data</summary>
  119.     struct LightObject
  120.     {
  121.         public Vector4 Position; // Position in world space
  122.         public Vector4 MoveDirection; // Direction in which it moves
  123.         public float MoveDistance; // Maximum distance it can move
  124.         public Matrix WorldMatrix; // World transform matrix for the light before animation
  125.         public Matrix WorkingMatrix; // Working matrix (world transform after animation)
  126.     }
  127.     /// <summary>Stores cached handles for an effect in a technique group</summary>
  128.     struct TechniqueGroup
  129.     {
  130.         public EffectHandle RenderScene;
  131.         public EffectHandle RenderLight;
  132.         public EffectHandle RenderEnvMap;
  133.     }
  134.  
  135.     /// <summary>Class for rendering high dynamic range cube maps</summary>
  136.     public class HDRCubeMap : IFrameworkCallback, IDeviceCreation
  137.     {
  138.         #region Creation
  139.         /// <summary>Create a new instance of the class</summary>
  140.         public HDRCubeMap(Framework f) 
  141.         { 
  142.             // Store framework
  143.             sampleFramework = f; 
  144.             // Create dialogs
  145.             hud = new Dialog(sampleFramework); 
  146.         }
  147.         #endregion
  148.  
  149.         // Constants
  150.         private const int EnvironmentMapSize = 256;
  151.         // Currently, 4 is the only number of lights supported.
  152.         private const int NumberLights = 4;
  153.         private const float LightMeshRadius = 0.2f;
  154.         private static readonly int HelpTextColor = new ColorValue(0.0f, 1.0f, 0.3f, 1.0f).ToArgb();
  155.         private static readonly VertexElement[] decl = new VertexElement[] {
  156.             new VertexElement(0, 0, DeclarationType.Float3, DeclarationMethod.Default, DeclarationUsage.Position, 0), 
  157.             new VertexElement(0, 12, DeclarationType.Float3, DeclarationMethod.Default, DeclarationUsage.Normal, 0), 
  158.             new VertexElement(0, 24, DeclarationType.Float2, DeclarationMethod.Default, DeclarationUsage.TextureCoordinate, 0), 
  159.             VertexElement.VertexDeclarationEnd };
  160.  
  161.         // The meshes that will be the reflecting meshes, not required to be these meshes
  162.         private static readonly string[] MeshFileNames = new string[] {
  163.                 "misc\\teapot.x",
  164.                 "misc\\skullocc.x",
  165.                 "misc\\car.x"};
  166.  
  167.         // Mesh file to use for orbiter objects
  168.         // These don't have to use the same mesh file.
  169.         private static readonly OrbitData[] OrbitersInfo = new OrbitData[] {
  170.             new OrbitData("airplane\\airplane 2.x", new Vector3(-1.0f, 0.0f, 0.0f), 2.0f, (float)Math.PI), 
  171.             new OrbitData("airplane\\airplane 2.x", new Vector3(0.3f, 1.0f, 0.3f), 2.5f, (float)Math.PI / 2.0f) };
  172.                                                                                
  173.         // Variables
  174.         private Framework sampleFramework = null; // Framework for samples
  175.         private Font statsFont = null; // Font for drawing text
  176.         private Sprite textSprite = null; // Sprite for batching text calls
  177.         private Effect effect = null; // D3DX Effect Interface
  178.         private ModelViewerCamera camera = new ModelViewerCamera(); // A model viewing camera
  179.         private bool isHelpShowing = true; // If true, renders the UI help text
  180.         private Dialog hud = null; // dialog for standard controls
  181.         private LightObject[] lights = new LightObject[NumberLights]; // Parameters of light objects
  182.         private Vector4[] lightPositions = new Vector4[NumberLights]; // Positions of the lights in space
  183.         private Vector4 lightIntensity; // Light intensity
  184.         private SceneObject[] envMeshes = new SceneObject[MeshFileNames.Length]; // Mesh to receive environment mapping
  185.         private int currentMesh = 0; // Index of mesh that is being displayed
  186.         private FrameworkMesh roomMesh; // Mesh representing room (wall, floor, ceiling)
  187.         private FrameworkMesh lightMesh; // Mesh for the light object
  188.         private Orbiter[] orbiters = new Orbiter[OrbitersInfo.Length]; // Orbiter meshes
  189.  
  190.         private VertexDeclaration vertexDecl = null; // Vertex decl for the sample
  191.         private CubeTexture[] cubeMapFloating = new CubeTexture[2]; // Floating point format cubemap
  192.         private CubeTexture cubeMapInt32 = null; // 32-bit cube map (for fallback)
  193.         private Surface depthCube = null; // Depth-stencil buffer for rendering to cube texture
  194.         private int numberFloatingCube = 0; // Number of cube maps required for using floating point
  195.         private TechniqueGroup[] groupFloating = new TechniqueGroup[2]; // Group of techniques to use with floating pointcubemaps (2 cubes max)
  196.         private TechniqueGroup groupInt32; // Group of techniques to use with integer cubemaps
  197.  
  198.         private TechniqueGroup[] currentTechGroup; // Technique group currently used
  199.         private CubeTexture[] currentCubeTexture; // Cube Texture currently used
  200.  
  201.         // Handles for effect
  202.         private EffectHandle worldViewHandle = null; // Handle for world+view matrix in effect
  203.         private EffectHandle projHandle = null; // Handle for projection matrix in effect
  204.         private EffectHandle[] cubeTextureHandle = new EffectHandle[2]; // Handle for the cube texture in effect
  205.         private EffectHandle sceneTextureHandle = null; // Handle for the scene texture in effect
  206.         private EffectHandle lightIntensityHandle = null; // Handle for the light intensity in effect
  207.         private EffectHandle lightPositionHandle = null; // Handle for view space light positions in effect
  208.         private EffectHandle reflectivityHandle = null; // Handle for reflectivity in effect
  209.  
  210.         private int numberCubes; // Number of cube maps used based on current cubemap format
  211.  
  212.         private bool usingFloatCubeMap; // Whether we use floating point format cube map
  213.         private float reflectivity; // Reflectivity value. Ranges from 0 to 1.
  214.  
  215.         // HUD Ui Control constants
  216.         private const int ToggleFullscreen = 1;
  217.         private const int ToggleReference = 3;
  218.         private const int ChangeDevice = 4;
  219.         private const int ChangeMesh = 5;
  220.         private const int ResetParams = 6;
  221.         private const int SliderLightText = 7;
  222.         private const int SliderLight = 8;
  223.         private const int SliderReflectText = 9;
  224.         private const int SliderReflect = 10;
  225.         private const int CheckHDR = 11;
  226.  
  227.         /// <summary>
  228.         /// Called during device initialization, this code checks the device for some 
  229.         /// minimum set of capabilities, and rejects those that don't pass by returning false.
  230.         /// </summary>
  231.         public bool IsDeviceAcceptable(Caps caps, Format adapterFormat, Format backBufferFormat, bool windowed)
  232.         {
  233.             // Skip back buffer formats that don't support alpha blending
  234.             if (!Manager.CheckDeviceFormat(caps.AdapterOrdinal, caps.DeviceType, adapterFormat, 
  235.                 Usage.QueryPostPixelShaderBlending, ResourceType.Textures, backBufferFormat))
  236.                 return false;
  237.  
  238.             // Must support cube textures
  239.             if (!caps.TextureCaps.SupportsCubeMap)
  240.                 return false;
  241.  
  242.             // Must support pixel shader 2.0
  243.             if (caps.PixelShaderVersion < new Version(2,0))
  244.                 return false;
  245.  
  246.             // Need to support Format.A16B16R16F render target
  247.             if (!Manager.CheckDeviceFormat(caps.AdapterOrdinal, caps.DeviceType, adapterFormat, Usage.RenderTarget,
  248.                 ResourceType.CubeTexture, Format.A16B16G16R16F))
  249.             {
  250.                 // If not, need to support Format.G16R16F render target as fallback
  251.                 if (!Manager.CheckDeviceFormat(caps.AdapterOrdinal, caps.DeviceType, adapterFormat, Usage.RenderTarget,
  252.                     ResourceType.CubeTexture, Format.G16R16F))
  253.                 {
  254.                     return false;
  255.                 }
  256.             }
  257.             
  258.  
  259.             // Need to support Format.A8R8G8B8 render target
  260.             if (!Manager.CheckDeviceFormat(caps.AdapterOrdinal, caps.DeviceType, adapterFormat, Usage.RenderTarget,
  261.                 ResourceType.CubeTexture, Format.A8R8G8B8))
  262.             {
  263.                 return false;
  264.             }
  265.  
  266.             return true;
  267.         }
  268.  
  269.         /// <summary>
  270.         /// This callback function is called immediately before a device is created to allow the 
  271.         /// application to modify the device settings. The supplied settings parameter 
  272.         /// contains the settings that the framework has selected for the new device, and the 
  273.         /// application can make any desired changes directly to this structure.  Note however that 
  274.         /// the sample framework will not correct invalid device settings so care must be taken 
  275.         /// to return valid device settings, otherwise creating the Device will fail.  
  276.         /// </summary>
  277.         public void ModifyDeviceSettings(DeviceSettings settings, Caps caps)
  278.         {
  279.             // Initialize the number of cube maps required when using floating point format
  280.             if (!Manager.CheckDeviceFormat(caps.AdapterOrdinal, caps.DeviceType, settings.AdapterFormat, Usage.RenderTarget,
  281.                 ResourceType.CubeTexture, Format.A16B16G16R16F))
  282.             {
  283.                 numberCubes = numberFloatingCube = 2;
  284.             }
  285.             else
  286.             {
  287.                 numberCubes = numberFloatingCube = 1;
  288.             }
  289.  
  290.             // If device doesn't support HW T&L or doesn't support 1.1 vertex shaders in HW 
  291.             // then switch to SWVP.
  292.             if ( (!caps.DeviceCaps.SupportsHardwareTransformAndLight) ||
  293.                 (caps.VertexShaderVersion < new Version(1,1)) )
  294.             {
  295.                 settings.BehaviorFlags = CreateFlags.SoftwareVertexProcessing;
  296.             }
  297.             else
  298.             {
  299.                 settings.BehaviorFlags = CreateFlags.HardwareVertexProcessing;
  300.             }
  301.  
  302.             // This application is designed to work on a pure device by not using 
  303.             // any get methods, so create a pure device if supported and using HWVP.
  304.             if ( (caps.DeviceCaps.SupportsPureDevice) && 
  305.                 ((settings.BehaviorFlags & CreateFlags.HardwareVertexProcessing) != 0 ) )
  306.                 settings.BehaviorFlags |= CreateFlags.PureDevice;
  307.  
  308.             // Debugging vertex shaders requires either REF or software vertex processing 
  309.             // and debugging pixel shaders requires REF.  
  310. #if(DEBUG_VS)
  311.             if (settings.DeviceType != DeviceType.Reference )
  312.             {
  313.                 settings.BehaviorFlags &= ~CreateFlags.HardwareVertexProcessing;
  314.                 settings.BehaviorFlags |= CreateFlags.SoftwareVertexProcessing;
  315.             }
  316. #endif
  317. #if(DEBUG_PS)
  318.             settings.DeviceType = DeviceType.Reference;
  319. #endif
  320.  
  321.         }
  322.  
  323.         /// <summary>
  324.         /// This event will be fired immediately after the Direct3D device has been 
  325.         /// created, which will happen during application initialization and windowed/full screen 
  326.         /// toggles. This is the best location to create Pool.Managed resources since these 
  327.         /// resources need to be reloaded whenever the device is destroyed. Resources created  
  328.         /// here should be released in the Disposing event. 
  329.         /// </summary>
  330.         private void OnCreateDevice(object sender, DeviceEventArgs e)
  331.         {
  332.             // Initialize the stats font
  333.             statsFont = ResourceCache.GetGlobalInstance().CreateFont(e.Device, 15, 0, FontWeight.Bold, 1, false, CharacterSet.Default,
  334.                 Precision.Default, FontQuality.Default, PitchAndFamily.FamilyDoNotCare | PitchAndFamily.DefaultPitch
  335.                 , "Arial");
  336.  
  337.             // Define DEBUG_VS and/or DEBUG_PS to debug vertex and/or pixel shaders with the 
  338.             // shader debugger. Debugging vertex shaders requires either REF or software vertex 
  339.             // processing, and debugging pixel shaders requires REF.  The 
  340.             // ShaderFlags.Force*SoftwareNoOptimizations flag improves the debug experience in the 
  341.             // shader debugger.  It enables source level debugging, prevents instruction 
  342.             // reordering, prevents dead code elimination, and forces the compiler to compile 
  343.             // against the next higher available software target, which ensures that the 
  344.             // unoptimized shaders do not exceed the shader model limitations.  Setting these 
  345.             // flags will cause slower rendering since the shaders will be unoptimized and 
  346.             // forced into software.  See the DirectX documentation for more information about 
  347.             // using the shader debugger.
  348.             ShaderFlags shaderFlags = ShaderFlags.None;
  349. #if(DEBUG_VS)
  350.             shaderFlags |= ShaderFlags.ForceVertexShaderSoftwareNoOptimizations;
  351. #endif
  352. #if(DEBUG_PS)
  353.             shaderFlags |= ShaderFlags.ForcePixelShaderSoftwareNoOptimizations;
  354. #endif
  355.             // Read the D3DX effect file
  356.             string path = Utility.FindMediaFile("HDRCubeMap.fx");
  357.             effect = ResourceCache.GetGlobalInstance().CreateEffectFromFile(e.Device,
  358.                 path, null, null, shaderFlags, null);
  359.  
  360.             // Store the handles
  361.             worldViewHandle = effect.GetParameter(null, "worldViewMatrix");
  362.             projHandle = effect.GetParameter(null, "projMatrix");
  363.             cubeTextureHandle[0] = effect.GetParameter(null, "cubeMapTexture");
  364.             cubeTextureHandle[1] = effect.GetParameter(null, "cubeMapTexture2");
  365.             sceneTextureHandle = effect.GetParameter(null, "sceneTexture");
  366.             lightIntensityHandle = effect.GetParameter(null, "lightIntensityVector");
  367.             reflectivityHandle = effect.GetParameter(null, "reflectivity");
  368.             lightPositionHandle = effect.GetParameter(null, "lightPositionView");
  369.  
  370.             // Determine the technique to render with
  371.  
  372.             // Integer cube map
  373.             groupInt32.RenderScene = effect.GetTechnique("RenderScene");
  374.             groupInt32.RenderLight = effect.GetTechnique("RenderLight");
  375.             groupInt32.RenderEnvMap = effect.GetTechnique("RenderHDREnvMap");
  376.  
  377.             // Floating point cubemaps
  378.             if (numberFloatingCube == 2)
  379.             {
  380.                 // Two floating point G16R16F cube maps
  381.                 groupFloating[0].RenderScene = effect.GetTechnique("RenderSceneFirstHalf");
  382.                 groupFloating[0].RenderLight = effect.GetTechnique("RenderLightFirstHalf");
  383.                 groupFloating[0].RenderEnvMap = effect.GetTechnique("RenderHDREnvMap2Tex");
  384.                 groupFloating[1].RenderScene = effect.GetTechnique("RenderSceneSecondHalf");
  385.                 groupFloating[1].RenderLight = effect.GetTechnique("RenderLightSecondHalf");
  386.                 groupFloating[1].RenderEnvMap = effect.GetTechnique("RenderHDREnvMap2Tex");
  387.             }
  388.             else
  389.             {
  390.                 // Single floating point cube map
  391.                 groupFloating[0].RenderScene = effect.GetTechnique("RenderScene");
  392.                 groupFloating[0].RenderLight = effect.GetTechnique("RenderLight");
  393.                 groupFloating[0].RenderEnvMap = effect.GetTechnique("RenderHDREnvMap");
  394.             }
  395.  
  396.             // Initialize reflectivity
  397.             effect.SetValue(reflectivityHandle, reflectivity);
  398.  
  399.             // Initialize light intensity
  400.             effect.SetValue(lightIntensityHandle, lightIntensity);
  401.  
  402.             // Create vertex declaration
  403.             vertexDecl = new VertexDeclaration(e.Device, decl);
  404.  
  405.             // Load the meshes
  406.             for(int i = 0; i < MeshFileNames.Length; i++)
  407.             {
  408.                 // Load the meshes
  409.                 envMeshes[i] = new SceneObject(LoadMesh(e.Device, MeshFileNames[i]));
  410.                 envMeshes[i].WorldCenterAndScaleToRadius(1.0f); // Scale to a radius of one
  411.             }
  412.  
  413.             // Load the room object
  414.             roomMesh = LoadMesh(e.Device, "room.x");
  415.  
  416.             // Load the light object
  417.             lightMesh = LoadMesh(e.Device, "misc\\sphere0.x");
  418.  
  419.             // Initialize the world matrices for the lights
  420.             Vector3 center;
  421.             float radius = lightMesh.ComputeBoundingSphere(out center);
  422.             float scaleFactor = LightMeshRadius / radius;
  423.             Matrix lightWorld = Matrix.Translation(-center) * Matrix.Scaling(scaleFactor, scaleFactor, scaleFactor);
  424.  
  425.             for (int i = 0; i < NumberLights; i++)
  426.             {
  427.                 lights[i].WorldMatrix = lightWorld * Matrix.Translation(lights[i].Position.X, lights[i].Position.Y, lights[i].Position.Z);
  428.             }
  429.  
  430.             // Load the orbiters
  431.             for (int i = 0; i < OrbitersInfo.Length; i++)
  432.             {
  433.                 orbiters[i] = new Orbiter(LoadMesh(e.Device, OrbitersInfo[i].MeshFile));
  434.                 orbiters[i].WorldCenterAndScaleToRadius(0.7f);
  435.                 orbiters[i].SetOrbit(OrbitersInfo[i].Axis, OrbitersInfo[i].Radius, OrbitersInfo[i].Speed);
  436.             }
  437.  
  438.             // World transform to identity
  439.             e.Device.Transform.World = Matrix.Identity;
  440.  
  441.             // Setup camera's view params
  442.             camera.SetViewParameters(new Vector3(0.0f, 0.0f, -2.5f), Vector3.Empty);
  443.         }
  444.         
  445.         /// <summary>
  446.         /// This event will be fired immediately after the Direct3D device has been 
  447.         /// reset, which will happen after a lost device scenario. This is the best location to 
  448.         /// create Pool.Default resources since these resources need to be reloaded whenever 
  449.         /// the device is lost. Resources created here should be released in the OnLostDevice 
  450.         /// event. 
  451.         /// </summary>
  452.         private void OnResetDevice(object sender, DeviceEventArgs e)
  453.         {
  454.             SurfaceDescription desc = e.BackBufferDescription;
  455.             // Create a sprite to help batch calls when drawing many lines of text
  456.             textSprite = new Sprite(e.Device);
  457.  
  458.             // Setup the camera's projection parameters
  459.             float aspectRatio = (float)desc.Width / (float)desc.Height;
  460.             camera.SetProjectionParameters((float)Math.PI / 4, aspectRatio, 0.1f, 1000.0f);
  461.             camera.SetWindow(desc.Width, desc.Height);
  462.             camera.SetRadius(3.0f, 1.0f, 6.0f);
  463.  
  464.             // Setup UI locations
  465.             hud.SetLocation(desc.Width-170, 0);
  466.             hud.SetSize(170,170);
  467.             // Move non-HUD items to lower part of screen
  468.             int y = desc.Height - 170;
  469.             Control c;
  470.             if ((c = hud.GetControl(CheckHDR)) != null)
  471.                 c.SetLocation(35, y);
  472.             if ((c = hud.GetControl(ChangeMesh)) != null)
  473.                 c.SetLocation(35, y += 24);
  474.             if ((c = hud.GetControl(ResetParams)) != null)
  475.                 c.SetLocation(35, y += 24);
  476.             if ((c = hud.GetControl(SliderLightText)) != null)
  477.                 c.SetLocation(35, y += 35);
  478.             if ((c = hud.GetControl(SliderLight)) != null)
  479.                 c.SetLocation(35, y += 17);
  480.             if ((c = hud.GetControl(SliderReflectText)) != null)
  481.                 c.SetLocation(35, y += 24);
  482.             if ((c = hud.GetControl(SliderReflect)) != null)
  483.                 c.SetLocation(35, y += 17);
  484.  
  485.             try
  486.             {
  487.                 // Create the cube textures
  488.                 cubeMapFloating[0] = new CubeTexture(e.Device, EnvironmentMapSize, 1, Usage.RenderTarget,
  489.                     Format.A16B16G16R16F, Pool.Default);
  490.             }
  491.             catch
  492.             {
  493.                 // Create 2 G16R16 textures as fallback
  494.                 cubeMapFloating[0] = new CubeTexture(e.Device, EnvironmentMapSize, 1, Usage.RenderTarget,
  495.                     Format.G16R16, Pool.Default);
  496.                 cubeMapFloating[1] = new CubeTexture(e.Device, EnvironmentMapSize, 1, Usage.RenderTarget,
  497.                     Format.G16R16, Pool.Default);
  498.             }
  499.  
  500.             // Create the integer cube map
  501.             cubeMapInt32 = new CubeTexture(e.Device, EnvironmentMapSize, 1, Usage.RenderTarget,
  502.                 Format.A8R8G8B8, Pool.Default);
  503.  
  504.             // Create the stencil buffer to be used with the cube textures
  505.             DeviceSettings settings = sampleFramework.DeviceSettings;
  506.             depthCube = e.Device.CreateDepthStencilSurface(EnvironmentMapSize, EnvironmentMapSize, 
  507.                 settings.presentParams.AutoDepthStencilFormat, MultiSampleType.None, 0, true);
  508.  
  509.             // Setup the current group information
  510.             currentTechGroup = new TechniqueGroup[2]; for (int i = 0; i < 2; i++) currentTechGroup[i] = groupFloating[i];
  511.             currentCubeTexture = new CubeTexture[2];  for (int i = 0; i < 2; i++) currentCubeTexture[i] = cubeMapFloating[i];
  512.         }
  513.  
  514.         /// <summary>
  515.         /// This event function will be called fired after the Direct3D device has 
  516.         /// entered a lost state and before Device.Reset() is called. Resources created
  517.         /// in the OnResetDevice callback should be released here, which generally includes all 
  518.         /// Pool.Default resources. See the "Lost Devices" section of the documentation for 
  519.         /// information about lost devices.
  520.         /// </summary>
  521.         private void OnLostDevice(object sender, EventArgs e)
  522.         {
  523.             if (textSprite != null)
  524.             {
  525.                 textSprite.Dispose();
  526.                 textSprite = null;
  527.             }
  528.  
  529.             // Now the textures/surfaces
  530.             if (cubeMapFloating[0] != null)
  531.                 cubeMapFloating[0].Dispose();
  532.             if (cubeMapFloating[1] != null)
  533.                 cubeMapFloating[1].Dispose();
  534.             if (cubeMapInt32 != null)
  535.                 cubeMapInt32.Dispose();
  536.             if (depthCube != null)
  537.                 depthCube.Dispose();
  538.             
  539.             // Set null
  540.             cubeMapFloating[0] = cubeMapFloating[1] = cubeMapInt32 = null;
  541.             depthCube = null;
  542.         }
  543.  
  544.         /// <summary>
  545.         /// This event will be fired immediately after the Direct3D device has 
  546.         /// been destroyed, which generally happens as a result of application termination or 
  547.         /// windowed/full screen toggles. Resources created in the OnCreateDevice event 
  548.         /// should be released here, which generally includes all Pool.Managed resources. 
  549.         /// </summary>
  550.         private void OnDestroyDevice(object sender, EventArgs e)
  551.         {
  552.             if (vertexDecl != null)
  553.                 vertexDecl.Dispose();
  554.             
  555.             if (roomMesh != null)
  556.                 roomMesh.Dispose();
  557.             
  558.             if (lightMesh != null)
  559.                 lightMesh.Dispose();
  560.  
  561.             for (int i = 0; i < MeshFileNames.Length; i++)
  562.                 if (envMeshes[i] != null)
  563.                     envMeshes[i].Mesh.Dispose();
  564.             for (int i = 0; i < orbiters.Length; i++)
  565.                 if (orbiters[i] != null)
  566.                     orbiters[i].Mesh.Dispose();
  567.         }
  568.  
  569.         /// <summary>
  570.         /// This callback function will be called once at the beginning of every frame. This is the
  571.         /// best location for your application to handle updates to the scene, but is not 
  572.         /// intended to contain actual rendering calls, which should instead be placed in the 
  573.         /// OnFrameRender callback.  
  574.         /// </summary>
  575.         public void OnFrameMove(Device device, double appTime, float elapsedTime)
  576.         {
  577.             // Update the camera's position based on user input 
  578.             camera.FrameMove(elapsedTime);
  579.  
  580.             // Update the orbiters
  581.             for (int i = 0; i < orbiters.Length; i++)
  582.                 orbiters[i].Orbit(elapsedTime);
  583.         }
  584.  
  585.         /// <summary>
  586.         /// This callback function will be called at the end of every frame to perform all the 
  587.         /// rendering calls for the scene, and it will also be called if the window needs to be 
  588.         /// repainted. After this function has returned, the sample framework will call 
  589.         /// Device.Present to display the contents of the next buffer in the swap chain
  590.         /// </summary>
  591.         public void OnFrameRender(Device device, double appTime, float elapsedTime)
  592.         {
  593.             bool beginSceneCalled = false;
  594.  
  595.             RenderSceneIntoCubeMap(device, appTime);
  596.  
  597.             // Clear the render target and the zbuffer 
  598.             device.Clear(ClearFlags.ZBuffer | ClearFlags.Target, 0x000000ff, 1.0f, 0);
  599.             try
  600.             {
  601.                 // Begin the scene
  602.                 device.BeginScene();
  603.                 beginSceneCalled = true;
  604.  
  605.                 RenderScene(device, camera.ViewMatrix, camera.ProjectionMatrix, currentTechGroup[0], true, appTime);
  606.  
  607.                 // Show frame rate
  608.                 RenderText();
  609.  
  610.                 // Show UI
  611.                 hud.OnRender(elapsedTime);
  612.             }
  613.             finally
  614.             {
  615.                 if (beginSceneCalled)
  616.                     device.EndScene();
  617.             }
  618.         }
  619.  
  620.         /// <summary>Set up the cube map by rendering the scene into it</summary>
  621.         private void RenderSceneIntoCubeMap(Device device, double appTime)
  622.         {
  623.             // The projection matrix has a FOV of 90 degrees and asp ratio of 1
  624.             Matrix proj = Matrix.PerspectiveFovLH((float)Math.PI * 0.5f, 1.0f, 0.01f, 100.0f);
  625.             Matrix viewDir = camera.ViewMatrix;
  626.             viewDir.M41 = viewDir.M42 = viewDir.M43 = 0.0f;
  627.  
  628.             using (Surface oldRenderTarget = device.GetRenderTarget(0))
  629.             {
  630.                 Surface oldDepthStencil = null;
  631.  
  632.                 // Ignore any exceptions for this call
  633.                 DirectXException.IgnoreExceptions();
  634.                 oldDepthStencil = device.DepthStencilSurface;
  635.                 DirectXException.EnableExceptions();
  636.  
  637.                 // If the device has a depth-stencil buffer, use
  638.                 // the depth stencil buffer created for the cube textures.
  639.                 if (oldDepthStencil != null)
  640.                     device.DepthStencilSurface = depthCube;
  641.  
  642.                 for (int c = 0; c < numberCubes; ++c)
  643.                 {
  644.                     for (int f = 0; f < 6; ++f)
  645.                     {
  646.                         using(Surface s = currentCubeTexture[c].GetCubeMapSurface((CubeMapFace)f, 0))
  647.                         {
  648.                             device.SetRenderTarget(0, s);
  649.                             Matrix viewMatrix = viewDir * Utility.GetCubeMapViewMatrix(f);
  650.  
  651.                             // Clear the scene
  652.                             device.Clear(ClearFlags.ZBuffer, 0x000000ff, 1.0f, 0);
  653.                             bool beginSceneCalled = false;
  654.  
  655.                             try
  656.                             {
  657.                                 // Begin the scene
  658.                                 device.BeginScene();
  659.                                 beginSceneCalled = true;
  660.  
  661.                                 RenderScene(device, viewMatrix, proj, currentTechGroup[c], false, appTime);
  662.                             }
  663.                             finally
  664.                             {
  665.                                 if (beginSceneCalled)
  666.                                     device.EndScene();
  667.                             }
  668.  
  669.                         }
  670.                     }
  671.                 }
  672.  
  673.                 // Restore the depth-stencil buffer and render target
  674.                 if (oldDepthStencil != null)
  675.                 {
  676.                     device.DepthStencilSurface = oldDepthStencil;
  677.                     oldDepthStencil.Dispose();
  678.                 }
  679.                 device.SetRenderTarget(0, oldRenderTarget);
  680.             }
  681.         }
  682.         /// <summary>Set up the cube map by rendering the scene into it</summary>
  683.         private void RenderScene(Device device, Matrix view, Matrix proj, TechniqueGroup techGroup,
  684.             bool renderEnvMappedMesh, double appTime)
  685.         {
  686.             int passes;
  687.             Matrix worldView;
  688.  
  689.             // Set the projection matrix
  690.             effect.SetValue(projHandle, proj);
  691.  
  692.             // Write camera-space light positions to effect
  693.             for (int i = 0; i < lightPositions.Length; i++)
  694.             {
  695.                 // Animate the lights
  696.                 float disp = ( 1.0f + (float)Math.Cos( (float)Math.IEEERemainder( (float)appTime, (float)Math.PI ) ) ) * 0.5f * lights[i].MoveDistance; // Distance to move
  697.                 Vector4 move = lights[i].MoveDirection * disp; // In vector form
  698.                 lights[i].WorkingMatrix = Matrix.Translation(move.X, move.Y, move.Z); // Matrix form
  699.                 lights[i].WorkingMatrix = lights[i].WorldMatrix * lights[i].WorkingMatrix;
  700.                 move += lights[i].Position; // Animated world coords
  701.                 lightPositions[i] = Vector4.Transform(move, view);
  702.             }
  703.             effect.SetValue(lightPositionHandle, lightPositions);
  704.  
  705.             //
  706.             // Render the environment-mapped mesh if specified
  707.             //
  708.  
  709.             if (renderEnvMappedMesh)
  710.             {
  711.                 effect.Technique = techGroup.RenderEnvMap;
  712.                 // Combine the offset and scaling transformation with
  713.                 // rotation from the camera to form the final
  714.                 // world transformation matrix.
  715.                 worldView = envMeshes[currentMesh].WorldMatrix * camera.WorldMatrix;
  716.                 worldView *= view;
  717.  
  718.                 effect.SetValue(worldViewHandle, worldView);
  719.                 passes = effect.Begin(0);
  720.  
  721.                 // Set the cube textures
  722.                 for (int i = 0; i < numberCubes; i++)
  723.                     effect.SetValue(cubeTextureHandle[i], currentCubeTexture[i]);
  724.  
  725.                 for (int iPass = 0; iPass < passes; iPass++)
  726.                 {
  727.                     effect.BeginPass(iPass);
  728.                     Mesh m = envMeshes[currentMesh].Mesh.LocalMesh;
  729.                     for (int i = 0; i < envMeshes[currentMesh].Mesh.NumberMaterials; ++i)
  730.                         m.DrawSubset(i);
  731.                     effect.EndPass();
  732.                 }
  733.                 effect.End();
  734.             }
  735.  
  736.             //
  737.             // Render light spheres
  738.             //
  739.             effect.Technique = techGroup.RenderLight;
  740.             passes = effect.Begin(0);
  741.             for (int p = 0; p < passes; ++p)
  742.             {
  743.                 effect.BeginPass(p);
  744.                 for (int i = 0; i < NumberLights; ++i)
  745.                 {
  746.                     worldView = lights[i].WorkingMatrix * view;
  747.                     effect.SetValue(worldViewHandle, worldView);
  748.                     effect.CommitChanges();
  749.                     lightMesh.Render(device);
  750.                 }
  751.                 effect.EndPass();
  752.             }
  753.             effect.End();
  754.  
  755.             //
  756.             // Render the rest of the scene
  757.             //
  758.             effect.Technique = techGroup.RenderScene;
  759.             passes = effect.Begin(0);
  760.             for (int p = 0; p < passes; ++p)
  761.             {
  762.                 effect.BeginPass(p);
  763.                 //
  764.                 // Orbiters
  765.                 //
  766.                 for (int i = 0; i < orbiters.Length; i++)
  767.                 {
  768.                     worldView = orbiters[i].WorldMatrix * view;
  769.                     effect.SetValue(worldViewHandle, worldView);
  770.  
  771.                     // Iterate through each subset and render with its texture
  772.                     for (int m = 0; m < orbiters[i].Mesh.NumberMaterials; ++m)
  773.                     {
  774.                         effect.SetValue(sceneTextureHandle, orbiters[i].Mesh.GetTexture(m));
  775.                         effect.CommitChanges();
  776.                         orbiters[i].Mesh.LocalMesh.DrawSubset(m);
  777.                     }
  778.                 }
  779.  
  780.                 //
  781.                 // The room object (walls, floor, ceiling)
  782.                 //
  783.                 effect.SetValue(worldViewHandle, view);
  784.                 // Iterate through each subset and render with its texture
  785.                 for (int m = 0; m < roomMesh.NumberMaterials; ++m)
  786.                 {
  787.                     effect.SetValue(sceneTextureHandle, roomMesh.GetTexture(m));
  788.                     effect.CommitChanges();
  789.                     roomMesh.LocalMesh.DrawSubset(m);
  790.                 }
  791.                 effect.EndPass();
  792.             }
  793.             effect.End();
  794.         }
  795.  
  796.         /// <summary>
  797.         /// Render the help and statistics text. This function uses the Font object for 
  798.         /// efficient text rendering.
  799.         /// </summary>
  800.         private void RenderText()
  801.         {
  802.             TextHelper txtHelper = new TextHelper(statsFont, textSprite, 15);
  803.  
  804.             // Output statistics
  805.             txtHelper.Begin();
  806.             txtHelper.SetInsertionPoint(5,5);
  807.             txtHelper.SetForegroundColor(System.Drawing.Color.Yellow);
  808.             txtHelper.DrawTextLine(sampleFramework.FrameStats);
  809.             txtHelper.DrawTextLine(sampleFramework.DeviceStats);
  810.  
  811.  
  812.             txtHelper.SetForegroundColor(System.Drawing.Color.Orange);
  813.             // Draw help
  814.             if (isHelpShowing)
  815.             {
  816.                 txtHelper.SetInsertionPoint(10, sampleFramework.BackBufferSurfaceDescription.Height-15*12);
  817.                 txtHelper.DrawTextLine("Controls:");
  818.  
  819.                 txtHelper.SetInsertionPoint(40, sampleFramework.BackBufferSurfaceDescription.Height-15*11);
  820.                 txtHelper.DrawTextLine("Rotate object: Left drag mouse");
  821.                 txtHelper.DrawTextLine("Adjust camera: Right drag mouse\nZoom In/Out: Mouse wheel");
  822.                 txtHelper.DrawTextLine("\nAdjust reflectivity: E,D\nAdjust light intensity: W,S");
  823.                 txtHelper.DrawTextLine("\n\nHide help: F1");
  824.                 txtHelper.DrawTextLine("\n\nQuit: ESC");
  825.             }
  826.             else
  827.             {
  828.                 txtHelper.DrawTextLine("Press F1 for help");
  829.             }
  830.             
  831.             txtHelper.SetForegroundColor(System.Drawing.Color.LightGreen);
  832.             txtHelper.SetInsertionPoint(10, sampleFramework.BackBufferSurfaceDescription.Height - 48);
  833.             txtHelper.DrawTextLine("Cube map format");
  834.             txtHelper.DrawTextLine("Material reflectivity ( e/E, d/D )");
  835.             txtHelper.DrawTextLine("Light intensity ( w/W, s/S )");
  836.             txtHelper.SetInsertionPoint(190, sampleFramework.BackBufferSurfaceDescription.Height - 48);
  837.             txtHelper.DrawTextLine("{0}\n{1}\n{2}", usingFloatCubeMap ? "Floating-point (D3D9 / HDR)" : 
  838.                 "Integer (D3D8)", reflectivity, lightIntensity.X);
  839.  
  840.             txtHelper.End();
  841.         }
  842.  
  843.         /// <summary>
  844.         /// As a convenience, the sample framework inspects the incoming windows messages for
  845.         /// keystroke messages and decodes the message parameters to pass relevant keyboard
  846.         /// messages to the application.  The framework does not remove the underlying keystroke 
  847.         /// messages, which are still passed to the application's MsgProc callback.
  848.         /// </summary>
  849.         private void OnKeyEvent(System.Windows.Forms.Keys key, bool isKeyDown, bool isKeyUp)
  850.         {
  851.             if (isKeyDown)
  852.             {
  853.                 switch(key)
  854.                 {
  855.                     case System.Windows.Forms.Keys.F1:
  856.                         isHelpShowing = !isHelpShowing;
  857.                         break;
  858.                 }
  859.             }
  860.         }
  861.  
  862.         /// <summary>
  863.         /// Before handling window messages, the sample framework passes incoming windows 
  864.         /// messages to the application through this callback function. If the application sets 
  865.         /// noFurtherProcessing to true, the sample framework will not process the message
  866.         /// </summary>
  867.         public IntPtr OnMsgProc(IntPtr hWnd, NativeMethods.WindowMessage msg, IntPtr wParam, IntPtr lParam, ref bool noFurtherProcessing)
  868.         {
  869.             // Give the dialog a chance to handle the message first
  870.             noFurtherProcessing = hud.MessageProc(hWnd, msg, wParam, lParam);
  871.             if (noFurtherProcessing)
  872.                 return IntPtr.Zero;
  873.  
  874.             // Pass all remaining windows messages to camera so it can respond to user input
  875.             camera.HandleMessages(hWnd, msg, wParam, lParam);
  876.  
  877.             //
  878.             // Use NativeMethods.WindowMessage.Character to handle parameter adjustment so
  879.             // that we can control the granularity based on
  880.             // the letter cases.
  881.             if (msg == NativeMethods.WindowMessage.Character)
  882.             {
  883.                 char c = (char)wParam.ToInt32();
  884.                 switch(c)
  885.                 {
  886.                     case 'W':
  887.                     case 'w':
  888.                         if (c == 'w')
  889.                             lightIntensity += new Vector4(0.1f, 0.1f, 0.1f, 0.0f);
  890.                         else
  891.                             lightIntensity += new Vector4(10.0f, 10.0f, 10.0f, 0.0f);
  892.  
  893.                         if (lightIntensity.X > 150.0f)
  894.                         {
  895.                             lightIntensity.X =
  896.                             lightIntensity.Y =
  897.                             lightIntensity.Z = 150.0f;
  898.                         }
  899.  
  900.                         effect.SetValue(lightIntensityHandle, lightIntensity);
  901.                         UpdateUiWithChanges();
  902.                         break;
  903.                     case 'S':
  904.                     case 's':
  905.                         if (c == 's')
  906.                             lightIntensity -= new Vector4(0.1f, 0.1f, 0.1f, 0.0f);
  907.                         else
  908.                             lightIntensity -= new Vector4(10.0f, 10.0f, 10.0f, 0.0f);
  909.  
  910.                         if (lightIntensity.X < 0.0f)
  911.                         {
  912.                             lightIntensity.X =
  913.                             lightIntensity.Y =
  914.                             lightIntensity.Z = 0.0f;
  915.                         }
  916.  
  917.                         effect.SetValue(lightIntensityHandle, lightIntensity);
  918.                         UpdateUiWithChanges();
  919.                         break;
  920.                     case 'D':
  921.                     case 'd':
  922.                         if (c == 'd')
  923.                             reflectivity -= 0.01f;
  924.                         else
  925.                             reflectivity -= 0.1f;
  926.  
  927.                         if (reflectivity < 0.0f)
  928.                             reflectivity = 0.0f;
  929.  
  930.                         effect.SetValue(reflectivityHandle, reflectivity);
  931.                         UpdateUiWithChanges();
  932.                         break;
  933.                     case 'E':
  934.                     case 'e':
  935.                         if (c == 'e')
  936.                             reflectivity += 0.01f;
  937.                         else
  938.                             reflectivity += 0.1f;
  939.  
  940.                         if (reflectivity > 1.0f)
  941.                             reflectivity = 1.0f;
  942.  
  943.                         effect.SetValue(reflectivityHandle, reflectivity);
  944.                         UpdateUiWithChanges();
  945.                         break;
  946.                 }
  947.             }
  948.             return IntPtr.Zero;
  949.         }
  950.  
  951.         /// <summary>Load mesh from file and convert vertices to our format</summary>
  952.         private FrameworkMesh LoadMesh(Device device, string filename)
  953.         {
  954.             FrameworkMesh mesh = new FrameworkMesh(device, filename);
  955.             mesh.SetVertexDeclaration(device, decl);
  956.  
  957.             return mesh;
  958.         }
  959.  
  960.         /// <summary>Initializes the application</summary>
  961.         public void InitializeApplication()
  962.         {
  963.             // Change CheckBox default visual style
  964.             Element e = hud.GetDefaultElement(ControlType.CheckBox, 0);
  965.             e.FontColor.States[(int)ControlState.Normal] = new ColorValue(0, 1.0f, 0, 1.0f);
  966.  
  967.             // Change Static default visual style
  968.             e = hud.GetDefaultElement(ControlType.StaticText, 0);
  969.             e.textFormat = DrawTextFormat.Left | DrawTextFormat.Center;
  970.             e.FontColor.States[(int)ControlState.Normal] = new ColorValue(0, 1.0f, 0, 1.0f);
  971.  
  972.             int y = 10;
  973.             // Initialize the dialogs
  974.             Button fullScreen = hud.AddButton(ToggleFullscreen,"Toggle full screen", 35, y, 125,22);
  975.             Button toggleRef = hud.AddButton(ToggleReference,"Toggle reference (F3)", 35, y += 24, 125,22);
  976.             Button changeDevice = hud.AddButton(ChangeDevice,"Change Device (F2)", 35, y += 24, 125,22);
  977.             Button changeMesh = hud.AddButton(ChangeMesh, "Change Mesh (N)", 35, y+=24, 125, 22, System.Windows.Forms.Keys.N, false);
  978.             Button resetParams = hud.AddButton(ResetParams, "Reset Paramters (R)", 35, y+=24, 125, 22, System.Windows.Forms.Keys.R, false);
  979.             Checkbox checkHdr = hud.AddCheckBox(CheckHDR, "Use HDR Texture (F)", 35, y+=24, 130, 22, true, System.Windows.Forms.Keys.F, false);
  980.             hud.AddStatic(SliderLightText, "Light Intensity", 35, y+=24, 125, 16);
  981.             Slider lightSlider = hud.AddSlider(SliderLight, 35, y += 17, 125, 22, 0, 1500, 0, false);
  982.             hud.AddStatic(SliderReflectText, "Reflectivity", 35, y+=24, 125, 16);
  983.             Slider reflectSlider = hud.AddSlider(SliderReflect, 35, y += 17, 125, 22);
  984.  
  985.             // Hook the button events for when these items are clicked
  986.             fullScreen.Click += new EventHandler(OnFullscreenClicked);
  987.             toggleRef.Click += new EventHandler(OnRefClicked);
  988.             changeDevice.Click += new EventHandler(OnChangeDevicClicked);
  989.             // Hook the other events
  990.             checkHdr.Changed += new EventHandler(OnChangeHdr);
  991.             changeMesh.Click += new EventHandler(OnChangeMesh);
  992.             resetParams.Click += new EventHandler(OnResetParams);
  993.             lightSlider.ValueChanged += new EventHandler(OnLightIntensityChanged);
  994.             reflectSlider.ValueChanged += new EventHandler(OnReflectChanged);
  995.  
  996.  
  997.             // Reset the parameters
  998.             ResetParameters();
  999.  
  1000.             // Initialize the camera parameters
  1001.             camera.SetModelCenter(Vector3.Empty);
  1002.             camera.IsPositionMovementEnabled = false;
  1003.  
  1004.             // Set the light positions
  1005.             lights[0].Position = new Vector4(-3.5f, 2.3f, -4.0f, 1.0f);
  1006.             lights[0].MoveDirection = new Vector4(0.0f, 0.0f, 1.0f, 0.0f);
  1007.             lights[0].MoveDistance = 8.0f;
  1008.             if (NumberLights > 1)
  1009.             {
  1010.                 lights[1].Position = new Vector4(3.5f, 2.3f,  4.0f, 1.0f);
  1011.                 lights[1].MoveDirection = new Vector4(0.0f, 0.0f, -1.0f, 0.0f);
  1012.                 lights[1].MoveDistance = 8.0f;
  1013.             }
  1014.             if (NumberLights > 2)
  1015.             {
  1016.                 lights[2].Position = new Vector4(-3.5f, 2.3f,  4.0f, 1.0f);
  1017.                 lights[2].MoveDirection = new Vector4(1.0f, 0.0f, 0.0f, 0.0f);
  1018.                 lights[2].MoveDistance = 7.0f;
  1019.             }
  1020.             if (NumberLights > 3)
  1021.             {
  1022.                 lights[3].Position = new Vector4(3.5f, 2.3f, -4.0f, 1.0f);
  1023.                 lights[3].MoveDirection = new Vector4(-1.0f, 0.0f, 0.0f, 0.0f);
  1024.                 lights[3].MoveDistance = 7.0f;
  1025.             }
  1026.  
  1027.         }
  1028.  
  1029.         /// <summary>Reset light and material parameters to default values</summary>
  1030.         private void ResetParameters()
  1031.         {
  1032.             usingFloatCubeMap = true;
  1033.             reflectivity = 0.4f;
  1034.             lightIntensity = new Vector4(24.0f, 24.0f, 24.0f, 24.0f);
  1035.  
  1036.             // Update the effect if it exists
  1037.             if (effect != null)
  1038.             {
  1039.                 effect.SetValue(reflectivityHandle, reflectivity);
  1040.                 effect.SetValue(lightIntensityHandle, lightIntensity);
  1041.             }
  1042.  
  1043.             UpdateUiWithChanges();
  1044.         }
  1045.  
  1046.         /// <summary>Updates the user interface with the current state of the scene</summary>
  1047.         private void UpdateUiWithChanges()
  1048.         {
  1049.             StaticText s = hud.GetStaticText(SliderLightText);
  1050.             s.SetText("Light Intensity: " + lightIntensity.X.ToString());
  1051.             s = hud.GetStaticText(SliderReflectText);
  1052.             s.SetText("Reflectivity: " + reflectivity.ToString());
  1053.  
  1054.             Slider sl = hud.GetSlider(SliderLight);
  1055.             sl.Value = (int)(lightIntensity.X * 10.0f);
  1056.             sl = hud.GetSlider(SliderReflect);
  1057.             sl.Value = (int)(reflectivity * 100.0f);
  1058.             Checkbox box = hud.GetCheckbox(CheckHDR);
  1059.             box.IsChecked = usingFloatCubeMap;
  1060.         }
  1061.  
  1062.         /// <summary>Called when the change device button is clicked</summary>
  1063.         private void OnChangeDevicClicked(object sender, EventArgs e)
  1064.         {
  1065.             sampleFramework.ShowSettingsDialog(!sampleFramework.IsD3DSettingsDialogShowing);
  1066.         }
  1067.  
  1068.         /// <summary>Called when the full screen button is clicked</summary>
  1069.         private void OnFullscreenClicked(object sender, EventArgs e)
  1070.         {
  1071.             sampleFramework.ToggleFullscreen();
  1072.         }
  1073.  
  1074.         /// <summary>Called when the ref button is clicked</summary>
  1075.         private void OnRefClicked(object sender, EventArgs e)
  1076.         {
  1077.             sampleFramework.ToggleReference();
  1078.         }
  1079.  
  1080.         /// <summary>
  1081.         /// Entry point to the program. Initializes everything and goes into a message processing 
  1082.         /// loop. Idle time is used to render the scene.
  1083.         /// </summary>
  1084.         static int Main() 
  1085.         {
  1086.             using(Framework sampleFramework = new Framework())
  1087.             {
  1088.                 HDRCubeMap sample = new HDRCubeMap(sampleFramework);
  1089.                 // Set the callback functions. These functions allow the sample framework to notify
  1090.                 // the application about device changes, user input, and windows messages.  The 
  1091.                 // callbacks are optional so you need only set callbacks for events you're interested 
  1092.                 // in. However, if you don't handle the device reset/lost callbacks then the sample 
  1093.                 // framework won't be able to reset your device since the application must first 
  1094.                 // release all device resources before resetting.  Likewise, if you don't handle the 
  1095.                 // device created/destroyed callbacks then the sample framework won't be able to 
  1096.                 // recreate your device resources.
  1097.                 sampleFramework.Disposing += new EventHandler(sample.OnDestroyDevice);
  1098.                 sampleFramework.DeviceLost += new EventHandler(sample.OnLostDevice);
  1099.                 sampleFramework.DeviceCreated += new DeviceEventHandler(sample.OnCreateDevice);
  1100.                 sampleFramework.DeviceReset += new DeviceEventHandler(sample.OnResetDevice);
  1101.  
  1102.                 sampleFramework.SetKeyboardCallback(new KeyboardCallback(sample.OnKeyEvent));
  1103.                 sampleFramework.SetWndProcCallback(new WndProcCallback(sample.OnMsgProc));
  1104.  
  1105.                 sampleFramework.SetCallbackInterface(sample);
  1106.                 try
  1107.                 {
  1108.  
  1109.                     // Show the cursor and clip it when in full screen
  1110.                     sampleFramework.SetCursorSettings(true, true);
  1111.  
  1112.                     // Initialize
  1113.                     sample.InitializeApplication();
  1114.  
  1115.                     // Initialize the sample framework and create the desired window and Direct3D 
  1116.                     // device for the application. Calling each of these functions is optional, but they
  1117.                     // allow you to set several options which control the behavior of the sampleFramework.
  1118.                     sampleFramework.Initialize( true, true, true ); // Parse the command line, handle the default hotkeys, and show msgboxes
  1119.                     sampleFramework.CreateWindow("HDRCubeMap");
  1120.                     sampleFramework.CreateDevice( 0, true, Framework.DefaultSizeWidth, Framework.DefaultSizeHeight, 
  1121.                         sample);
  1122.  
  1123.                     // Pass control to the sample framework for handling the message pump and 
  1124.                     // dispatching render calls. The sample framework will call your FrameMove 
  1125.                     // and FrameRender callback when there is idle time between handling window messages.
  1126.                     sampleFramework.MainLoop();
  1127.  
  1128.                 }
  1129. #if(DEBUG)
  1130.                 catch (Exception e)
  1131.                 {
  1132.                     // In debug mode show this error (maybe - depending on settings)
  1133.                     sampleFramework.DisplayErrorMessage(e);
  1134. #else
  1135.             catch
  1136.             {
  1137.                 // In release mode fail silently
  1138. #endif
  1139.                     // Ignore any exceptions here, they would have been handled by other areas
  1140.                     return (sampleFramework.ExitCode == 0) ? 1 : sampleFramework.ExitCode; // Return an error code here
  1141.                 }
  1142.  
  1143.                 // Perform any application-level cleanup here. Direct3D device resources are released within the
  1144.                 // appropriate callback functions and therefore don't require any cleanup code here.
  1145.                 return sampleFramework.ExitCode;
  1146.             }
  1147.         }
  1148.  
  1149.         #region Sample UI Event Handlers
  1150.         private void OnChangeHdr(object sender, EventArgs e)
  1151.         {
  1152.             Checkbox cb = sender as Checkbox;
  1153.             usingFloatCubeMap = cb.IsChecked;
  1154.             if (usingFloatCubeMap)
  1155.             {
  1156.                 numberCubes = numberFloatingCube;
  1157.                 // Setup the current group information
  1158.                 for (int i = 0; i < 2; i++) currentTechGroup[i] = groupFloating[i];
  1159.                 for (int i = 0; i < 2; i++) currentCubeTexture[i] = cubeMapFloating[i];
  1160.             }
  1161.             else
  1162.             {
  1163.                 numberCubes = 1;
  1164.                 currentCubeTexture[0] = cubeMapInt32;
  1165.                 currentTechGroup[0] = groupInt32;
  1166.             }
  1167.         }
  1168.  
  1169.         private void OnChangeMesh(object sender, EventArgs e)
  1170.         {
  1171.             if(++currentMesh == MeshFileNames.Length)
  1172.                 currentMesh = 0;
  1173.         }
  1174.  
  1175.         private void OnResetParams(object sender, EventArgs e)
  1176.         {
  1177.             ResetParameters();
  1178.         }
  1179.  
  1180.         private void OnLightIntensityChanged(object sender, EventArgs e)
  1181.         {
  1182.             Slider sl = sender as Slider;
  1183.             lightIntensity.X = lightIntensity.Y = lightIntensity.Z = sl.Value * 0.1f;
  1184.             if (effect != null)
  1185.                 effect.SetValue(lightIntensityHandle, lightIntensity);
  1186.             UpdateUiWithChanges();
  1187.         }
  1188.  
  1189.         private void OnReflectChanged(object sender, EventArgs e)
  1190.         {
  1191.             Slider sl = sender as Slider;
  1192.             reflectivity = sl.Value * 0.01f;
  1193.             if (effect != null)
  1194.                 effect.SetValue(reflectivityHandle, reflectivity);
  1195.             UpdateUiWithChanges();
  1196.         }
  1197.         #endregion
  1198.     }
  1199. }
  1200.